using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Configuration;

namespace OpcClientSample
{
    internal class OpcuaService
    {
        Uri uri { get; set; }
        bool safe { get; set; }
        ApplicationInstance Application { get; set; }
        ApplicationDescription ApplicationDescription { get; set; }
        ApplicationConfiguration ApplicationConfig { get; set; }
        EndpointConfiguration m_endpoint { get; set; }
        Session m_session { get; set; }
        public OpcuaService() { }

        public OpcuaService(string url,bool safe)
        {
            uri = new Uri(url);
            this.safe = safe;
            Application = new ApplicationInstance();
            ApplicationDescription = new ApplicationDescription();
            ApplicationDescription.ApplicationUri="opc.tcp://172.20.74.1:9347";
            ApplicationDescription.ApplicationName="TestSample";

            ApplicationConfig = Application.ApplicationConfiguration;
            ApplicationConfig.ApplicationName = "TestSample";
            ApplicationConfig.ApplicationUri = "opc.tcp://172.20.74.1:9347";

            m_endpoint = EndpointConfiguration.Create(ApplicationConfig);
            m_endpoint.OperationTimeout = 10000;
        }
        IUserIdentity UserIdentity { get; set; }
        IList<string> preDataList { get; set; }
        public async Task<Session> ConnectAsync()
        {
            var session = await Session.Create(
                ApplicationConfig, new ConfiguredEndpoint(ApplicationDescription,m_endpoint), false,
                "TestSample", 10000, UserIdentity, preDataList).ConfigureAwait(false);

            var Endpoint = session.ConfiguredEndpoint;

            session.KeepAlive += Session_KeepAlive;

            session.ReturnDiagnostics = DiagnosticsMasks.SymbolicIdAndText;
            return session;
        }

        private void Session_KeepAlive(ISession session, KeepAliveEventArgs e)
        {
            if (ServiceResult.IsBad(e.Status))
            {
                session?.Dispose();
            }
        }

        private void ReadAttribute()
        {
            NodeId node = NodeId.Parse("ns=2;s=DRLaser/InKKNum");

            var namespaceUris = m_session.NamespaceUris;
            var testSet = GetTestSetStatic(namespaceUris).ToList();
            testSet.AddRange(GetTestSetSimulation(namespaceUris));
            foreach (var nodeId in testSet)
            {
                var dataValue = Session.ReadValue(nodeId);
                Assert.NotNull(dataValue);
                Assert.NotNull(dataValue.Value);
                Assert.AreNotEqual(DateTime.MinValue, dataValue.SourceTimestamp);
                Assert.AreNotEqual(DateTime.MinValue, dataValue.ServerTimestamp);
            }
        }
        /// <summary>
        /// Return a test set of nodes with static character.
        /// </summary>
        /// <param name="namespaceUris">The namesapce table used in the session.</param>
        /// <returns>The list of static test nodes.</returns>
        public IList<NodeId> GetTestSetStatic(NamespaceTable namespaceUris)
        {
            var TestSetStatic = CommonTestWorkers.NodeIdTestSetStatic;
            return TestSetStatic.Select(n => ExpandedNodeId.ToNodeId(n, namespaceUris)).Where(n => n != null).ToList();
        }
    }
}
